home *** CD-ROM | disk | FTP | other *** search
/ A.C.E. 2 / ACE CD 2.iso / FILES / UTILS / GAMESDS3.DMS / GAMESDS3.adf / GDS_Examples.lha / Examples / bubble / bubbles.c < prev    next >
C/C++ Source or Header  |  1994-11-14  |  18KB  |  546 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <exec/memory.h>
  5. #include <exec/types.h>
  6. #include <graphics/gfx.h>
  7. #include <graphics/gfxbase.h>
  8.  
  9. #include <proto/exec.h>
  10. #include <proto/graphics.h>
  11.  
  12. #include "GameSmith:GameSmith.h"
  13. #include "GameSmith:include/libraries/libptrs.h"
  14. #include "bubble.h"
  15.  
  16. /*-------------------------------------------------------------------------*/
  17.  
  18. #define VIDEO_STEPS      30
  19. #define COLOR_GRADIENT   0x100            /* color change amount */
  20. #define VIDEO_REG         0x180            /* address of bg color reg */
  21. #define BGCOLOR         0xf00            /* max color value (bright red) */
  22. #define BGCOLOR_LONG      0x00ff0000      /* 8 bit color entry (bright red) */
  23. #define MIN_COLOR         0x000
  24.  
  25. /*-------------------------------------------------------------------------*/
  26. /* Function Prototypes                                                      */
  27.  
  28. void parser(int,char **);
  29. int setup(void);
  30. void build_copper(void);
  31. void move_image(void);
  32. void check_bounds(void);
  33. __stdargs void collision(struct anim_struct *,struct anim_struct *,
  34.      struct collision_struct *,struct collision_struct *);
  35. int check_close(void);
  36. void cleanup(void);
  37. void free_arrays(void);
  38.  
  39. /*-------------------------------------------------------------------------*/
  40. /* some global variables                                                   */
  41.  
  42. int bubble_cnt,swidth,sheight,smode,delay=0,random_x=11,random_y=9;
  43. int *x=NULL,*y=NULL,*speedx=NULL,*speedy=NULL,*reset=NULL,*last=NULL;
  44. int dlist;                        /* display list handle for anims */
  45.  
  46. struct BitMap *bm3=NULL;
  47.  
  48. struct anim_struct *bubble;
  49. int copheight;
  50.  
  51. /*-------------------------------------------------------------------------*/
  52.  
  53. unsigned short copper_list[256];   /* enough for our custom copper list */
  54.  
  55. struct gs_viewport vp =
  56.    {
  57.    NULL,                           /* ptr to next viewport */
  58.    NULL,                           /* ptr to color table */
  59.    0,                              /* number of colors in table */
  60.    copper_list,                  /* ptr to user copper list for both pages */
  61.    0,0,0,0,0,                     /* height, width, depth, bmheight, bmwidth */
  62.    0,0,                           /* top & left viewport offsets */
  63.    0,0,                           /* X & Y bitmap offsets */
  64.    GSVP_ALLOCBM,                  /* flags (alloc bitmaps) */
  65.    NULL,NULL,                     /* 2.xx & above compatibility stuff */
  66.    NULL,NULL,                     /* bitmap pointers */
  67.    NULL,                           /* future expansion */
  68.    0,0,0,0                        /* display clip (use nominal) */
  69.    };
  70.  
  71. struct display_struct bubble_display =
  72.    {
  73.    NULL,                           /* ptr to previous display view */
  74.    NULL,NULL,                     /* 2.xx & above compatibility stuff */
  75.    0,0,                           /* X and Y display offsets */
  76.    0,                              /* display mode ID */
  77.    4,4,                           /* sprite priorities (sprites in front of playfields) */
  78.    GSV_DOUBLE,                     /* flags */
  79.    &vp,                           /* ptr to 1st viewport */
  80.    NULL                           /* future expansion */
  81.    };
  82.  
  83. /***************************************************************************/
  84.  
  85. main(argc,argv)
  86. int argc;
  87. char *argv[];
  88.  
  89. {
  90.    int err,end=0;
  91.  
  92.    if (argc < 2)
  93.       {
  94.       printf("\nUSAGE: bubbles [number of bubbles] [HIRES] [SUPER] [VB delay intervals] [X speed] [Y speed]\n");
  95.       exit(01);
  96.       }
  97.    if (gs_open_libs(DOS|GRAPHICS,0))   /* open AmigaDOS libs */
  98.       exit(01);               /* if can't open libs, abort */
  99.    parser(argc,argv);         /* parse command line args */
  100.    if (err=setup())            /* if couldn't get set up... abort program */
  101.       {
  102.       printf("\nSetup error: %d\n",err);
  103.       gs_close_libs();         /* close all libraries */
  104.       exit(02);
  105.       }
  106.    Forbid();                  /* take over the entire machine */
  107.    while (!end)               /* this shows off speed */
  108.       {
  109.       move_image();            /* move them bubbles around */
  110.       end=check_close();      /* end when user hits left mouse button */
  111.       }
  112.    Permit();                  /* OK, let other things run while we clean up */
  113.    cleanup();                  /* close & deallocate everything */
  114.    gs_close_libs();            /* close all libraries */
  115. }
  116.  
  117. /***************************************************************************/
  118.  
  119. void parser(argc,argv)
  120. int argc;
  121. char *argv[];
  122.  
  123. {
  124.    bubble_cnt=atoi(argv[1]);   /* # anims to place on the screen */
  125.    swidth=320;                  /* default width & height */
  126.    sheight=200;
  127.    copheight=200;
  128.    smode=0;                     /* default mode of lores no lace */
  129.    #ifdef NTSC_MONITOR_ID
  130.       if (GfxBase->LibNode.lib_Version >= 36)   /* if WB 2.0 or higher */
  131.          {               /* this defeats mode promotion on AGA machines */
  132.          if (ModeNotAvailable(NTSC_MONITOR_ID))
  133.             {
  134.             smode = PAL_MONITOR_ID;
  135.             sheight=256;
  136.             copheight=256;
  137.             }
  138.          else
  139.             {
  140.             smode = NTSC_MONITOR_ID;
  141.             }
  142.          }
  143.    #endif
  144.    if (argc >= 3)
  145.       {
  146.       if (!(stricmp(argv[2],"DBL")))   /* check for double scan */
  147.          {
  148.          #ifdef DBLNTSC_MONITOR_ID
  149.          if (GfxBase->LibNode.lib_Version >= 39)   /* if WB 3.0 or higher */
  150.             {               /* try for mode promoted AGA display */
  151.             if (!ModeNotAvailable(DBLNTSC_MONITOR_ID))
  152.                {
  153.                smode = DBLNTSC_MONITOR_ID;
  154.                copheight=400;
  155.                }
  156.             else if (!ModeNotAvailable(DBLPAL_MONITOR_ID))
  157.                {
  158.                smode = DBLPAL_MONITOR_ID;
  159.                sheight=256;
  160.                copheight=512;
  161.                }
  162.             }
  163.          #endif
  164.          }
  165.       else if (!(stricmp(argv[2],"DBLHIRES")))   /* check for hires double scan */
  166.          {
  167.          #ifdef DBLNTSC_MONITOR_ID
  168.          if (GfxBase->LibNode.lib_Version >= 39)   /* if WB 3.0 or higher */
  169.             {               /* try for mode promoted AGA display */
  170.             if (!ModeNotAvailable(DBLNTSC_MONITOR_ID))
  171.                {
  172.                swidth=640;
  173.                smode = DBLNTSC_MONITOR_ID;
  174.                copheight=400;
  175.                sheight=400;
  176.                }
  177.             else if (!ModeNotAvailable(DBLPAL_MONITOR_ID))
  178.                {
  179.                swidth=640;
  180.                smode = DBLPAL_MONITOR_ID;
  181.                sheight=256;
  182.                copheight=512;
  183.                }
  184.             smode|=HIRES|LACE;
  185.             }
  186.          #endif
  187.          }
  188.       else if (!(stricmp(argv[2],"HIRES")))   /* check for hires spec */
  189.          {
  190.          swidth=640;
  191.          sheight=400;
  192.          smode|=HIRES|LACE;
  193.          }
  194.       else if (!(stricmp(argv[2],"SUPER")))   /* check for superhires72 */
  195.          {
  196.          #ifdef SUPER72_MONITOR_ID
  197.          if (GfxBase->LibNode.lib_Version >= 36)
  198.             {
  199.             if (!ModeNotAvailable(SUPER72_MONITOR_ID | SUPERLACE_KEY))
  200.                {
  201.                smode=SUPER72_MONITOR_ID | SUPERLACE_KEY;
  202.                swidth=800;
  203.                sheight=600;
  204.                copheight=300;
  205.                }
  206.             }
  207.          #endif
  208.          }
  209.       }
  210.    if (argc >= 4)
  211.       {
  212.       delay=atoi(argv[3]);      /* delay value in vertical blank intervals */
  213.       }
  214.    if (argc >= 5)               /* new random X speed range */
  215.       {
  216.       random_x=atoi(argv[4]);
  217.       if (random_x < 2)
  218.          random_x=2;
  219.       }
  220.    if (argc >= 6)               /* new random Y speed range */
  221.       {
  222.       random_y=atoi(argv[5]);
  223.       if (random_y < 2)
  224.          random_y=2;
  225.       }
  226. }
  227.  
  228. /***************************************************************************/
  229.  
  230. int setup()
  231.  
  232. {
  233.    int cnt,depth=0;
  234.    struct blit_struct *img;
  235.    struct anim_load_struct load;
  236.  
  237.    if (!(x=(int *)malloc(bubble_cnt*sizeof(int))))
  238.       return(-1);
  239.    if (!(y=(int *)malloc(bubble_cnt*sizeof(int))))
  240.       {
  241.       free_arrays();
  242.       return(-1);
  243.       }
  244.    if (!(speedx=(int *)malloc(bubble_cnt*sizeof(int))))
  245.       {
  246.       free_arrays();
  247.       return(-1);
  248.       }
  249.    if (!(speedy=(int *)malloc(bubble_cnt*sizeof(int))))
  250.       {
  251.       free_arrays();
  252.       return(-1);
  253.       }
  254.    if (!(last=(int *)malloc(bubble_cnt*sizeof(int))))
  255.       {
  256.       free_arrays();
  257.       return(-1);
  258.       }
  259.    if (!(reset=(int *)malloc(bubble_cnt*sizeof(int))))
  260.       {
  261.       free_arrays();
  262.       return(-1);
  263.       }
  264.    load.filename="bubble";            /* name of anim file */
  265.    load.cmap_size=8;                  /* number of bits per color value */
  266.    load.array_elements=bubble_cnt;   /* number of array elements desired */
  267.    load.flags=0L;                     /* no special load flags */
  268.    if (gs_load_anim(&load))         /* load the anim object */
  269.       {
  270.       free_arrays();
  271.       return(-1);
  272.       }
  273.    bubble=load.anim_ptr.anim;         /* ptr to bubble anim */
  274.    if (load.type)                     /* make sure it's an anim type */
  275.       {
  276.       FreeMem(load.cmap,load.cmap_entries*sizeof(long));
  277.       free_arrays();
  278.       if (load.type = 1)
  279.          gs_free_cplx((struct anim_cplx *)bubble,bubble_cnt);
  280.       return(-2);
  281.       }
  282.    img = bubble[0].list;            /* ptr to 1st image in anim sequence */
  283.    while (img)                        /* find max depth of anim */
  284.       {
  285.       if (img->depth > depth)
  286.          depth = img->depth;
  287.       if (img->next == img)         /* avoid infinite loop */
  288.          img=NULL;                  /* if single shot anim */
  289.       else
  290.          img=img->next;
  291.       }
  292.    vp.height = sheight;               /* set up display dimensions */
  293.    vp.width = swidth;
  294.    vp.depth = depth;
  295.    vp.bmheight = sheight;
  296.    vp.bmwidth = swidth;
  297.    bubble_display.modes = smode;
  298.    vp.num_colors=load.cmap_entries;
  299.    vp.color_table=load.cmap;         /* addr of color table */
  300.    build_copper();                  /* build custom copper list */
  301.    load.cmap[0]=BGCOLOR_LONG;         /* use our new background color */
  302.    if (gs_create_display(&bubble_display))
  303.       {
  304.       FreeMem(load.cmap,load.cmap_entries*sizeof(long));
  305.       free_arrays();
  306.       gs_free_anim(bubble,bubble_cnt);
  307.       return(-2);
  308.       }
  309.    FreeMem(load.cmap,load.cmap_entries*sizeof(long));   /* done with color table */
  310.    if ((dlist=gs_get_display_list()) < 0)   /* allocate a display list for anims */
  311.       {
  312.       free_arrays();
  313.       gs_free_anim(bubble,bubble_cnt);
  314.       return(-3);
  315.       }
  316.    bm3=gs_get_bitmap(vp.depth,vp.bmwidth,vp.bmheight,0);
  317.    gs_init_anim(dlist,vp.bitmap1,vp.bitmap2,bm3);   /* tell anim system about bitmaps */
  318.    gs_set_anim_bounds(dlist,0,0,swidth-1,sheight-1);   /* set bounds for anim objects */
  319.    gs_set_collision(dlist,&collision);   /* set ptr to collision handler */
  320.    for (cnt=0; cnt < bubble_cnt; cnt++)
  321.       {                              /* add all bubbles to a display list */
  322.       reset[cnt]=0;
  323.       last[cnt]=-1;
  324.       x[cnt] = gs_random(swidth);   /* random X,Y coords */
  325.       y[cnt] = gs_random(sheight);
  326.       while ((speedx[cnt] = gs_random(random_x)) == 0);
  327.       while ((speedy[cnt] = gs_random(random_y)) == 0);
  328.       if (cnt&1)
  329.          {
  330.          speedx[cnt]*=-1;
  331.          speedy[cnt]*=-1;
  332.          }
  333.       if (bm3)                        /* if restore bitmap */
  334.          {
  335.          bubble[cnt].flags|=ANIM_SAVE_BG;   /* use fastest display method (next to simple copy) */
  336.          if (bubble[cnt].flags & ANIM_CLEAR)
  337.             bubble[cnt].flags ^= ANIM_CLEAR;
  338.          if (bubble[cnt].flags & ANIM_COPY)
  339.             bubble[cnt].flags ^= ANIM_COPY;
  340.          }
  341.       if (gs_add_anim(dlist,(struct anim_struct *)&bubble[cnt],x[cnt],y[cnt]))
  342.          {
  343.          cleanup();                  /* release everything */
  344.          return(-4);                  /* return failure */
  345.          }
  346.       gs_set_anim_cell((struct anim_struct *)&bubble[cnt],gs_random(bubble[cnt].count));
  347.       }
  348.    gs_draw_anims(dlist);
  349.    check_bounds();
  350.    gs_next_anim_page(dlist);
  351.    gs_show_display(&bubble_display,1);
  352.    gs_flip_display(&bubble_display,1);
  353.    gs_open_vb_timer();
  354.    return(0);
  355. }
  356.  
  357. /***************************************************************************/
  358.  
  359. void build_copper()
  360.  
  361. /* build a custom copper list of background color changes */
  362.  
  363. {
  364.    int cnt,cnt2=0,video_gradient;
  365.    short bgcolor,gradient,ctable[15];
  366.  
  367.    bgcolor=BGCOLOR;
  368.    gradient=0;
  369.    video_gradient=(copheight/3)/15;
  370.    for (cnt=0; cnt < 15; cnt++)            /* build copper list */
  371.       {
  372.       if (cnt)
  373.          {
  374.          copper_list[cnt2++]=UC_WAIT;      /* copper wait instruction */
  375.          copper_list[cnt2++]=gradient;      /* y coord to wait on */
  376.          copper_list[cnt2++]=0;            /* x coord to wait on */
  377.          }
  378.       ctable[cnt]=bgcolor;
  379.       copper_list[cnt2++]=UC_SETCOLOR;      /* set color register */
  380.       copper_list[cnt2++]=0;               /* register number */
  381.       copper_list[cnt2++]=ctable[cnt];      /* value for register */
  382.       gradient+=video_gradient;
  383.       bgcolor-=COLOR_GRADIENT;
  384.       if (bgcolor < MIN_COLOR)
  385.          bgcolor=0;
  386.       }
  387.    copper_list[cnt2++]=UC_WAIT;            /* copper wait instruction */
  388.    copper_list[cnt2++]=gradient;            /* y coord to wait on */
  389.    copper_list[cnt2++]=0;                  /* x coord to wait on */
  390.    copper_list[cnt2++]=UC_SETCOLOR;
  391.    copper_list[cnt2++]=0;                  /* color number */
  392.    copper_list[cnt2++]=0;                  /* color value */
  393.    gradient=((copheight/3)*2)-video_gradient;   /* build bottom color gradient */
  394.    for (cnt=14; cnt >= 0; cnt--)            /* build copper list */
  395.       {
  396.       copper_list[cnt2++]=UC_WAIT;         /* copper wait instruction */
  397.       copper_list[cnt2++]=gradient;         /* y coord to wait on */
  398.       copper_list[cnt2++]=0;               /* x coord to wait on */
  399.       copper_list[cnt2++]=UC_SETCOLOR;      /* set color register */
  400.       copper_list[cnt2++]=0;               /* register number */
  401.       copper_list[cnt2++]=ctable[cnt];      /* value for register */
  402.       gradient+=video_gradient;
  403.       }
  404.    copper_list[cnt2++]=UC_END;            /* end coppper list */
  405. }
  406.  
  407. /***************************************************************************/
  408.  
  409. void move_image()
  410.  
  411. /* move and animate the graphic objects on the screen */
  412.  
  413. {
  414.    int cnt;
  415.  
  416.    if (gs_vb_time() < delay)
  417.       return;
  418.    gs_vb_timer_reset();
  419.    for (cnt=0; cnt < bubble_cnt; cnt++)
  420.       {
  421.       x[cnt]+=speedx[cnt];            /* move the object */
  422.       y[cnt]+=speedy[cnt];
  423.       gs_anim_obj((struct anim_struct *)&bubble[cnt],x[cnt],y[cnt]);
  424.       if (reset[cnt])               /* since anim doesn't loop, must reset */
  425.          {                           /* the sequence in the event of collision */
  426.          reset[cnt]=0;               /* start at 1st cell in anim sequence */
  427.          gs_set_anim_cell((struct anim_struct *)&bubble[cnt],0);
  428.          }
  429.       if (!bubble[cnt].collide)      /* if not colliding, clear last ptr */
  430.          last[cnt]=-1;
  431.       }
  432.    while (bubble_display.flags & GSV_FLIP);   /* while page not flipped yet */
  433.    gs_draw_anims(dlist);            /* draw them anim objects! */
  434.    check_bounds();                  /* bounce off of outer bitmap bounds */
  435.    gs_next_anim_page(dlist);         /* tell anim sys to use other bitmap */
  436.    gs_flip_display(&bubble_display,1);   /* switch to other display, sync */
  437. }
  438.  
  439. /***************************************************************************/
  440.  
  441. void check_bounds()
  442.  
  443. {
  444.    int cnt;
  445.  
  446.    for (cnt=0; cnt < bubble_cnt; cnt++)
  447.       {
  448.       if (bubble[cnt].flags & (ANIM_BOUNDS_X1|ANIM_BOUNDS_X2))
  449.          {
  450.          x[cnt]=bubble[cnt].x;   /* keep track of current location */
  451.          speedx[cnt]=-speedx[cnt];   /* reverse X direction */
  452.          reset[cnt]=1;            /* make bubble warp */
  453.          last[cnt]=-1;            /* no colliding */
  454.          }
  455.       if (bubble[cnt].flags & (ANIM_BOUNDS_Y1|ANIM_BOUNDS_Y2))
  456.          {
  457.          y[cnt]=bubble[cnt].y;
  458.          speedy[cnt]=-speedy[cnt];   /* reverse Y direction */
  459.          reset[cnt]=1;
  460.          last[cnt]=-1;
  461.          }
  462.       }
  463. }
  464.  
  465. /***************************************************************************/
  466.  
  467. int check_close()
  468.  
  469. /* check for user input */
  470.  
  471. {
  472.    if (gs_joystick(0) & (JOY_BUTTON1|JOY_BUTTON2))
  473.       return(1);
  474.    return(0);
  475. }
  476.  
  477. /***************************************************************************/
  478.  
  479. __stdargs void collision(anim1,anim2,coll1,coll2)
  480. struct anim_struct *anim1;
  481. struct anim_struct *anim2;
  482. struct collision_struct *coll1;
  483. struct collision_struct *coll2;
  484.  
  485. /*
  486.  
  487. This is the collision handler which makes the bubbles "bounce" off of
  488. each other.
  489.  
  490. */
  491.  
  492. {
  493.    int temp;
  494.  
  495.    if (last[anim1->array_num] != anim2->array_num)      /* if not same object */
  496.       {
  497.       last[anim1->array_num] = anim2->array_num;      /* remember last collision */
  498.       last[anim2->array_num] = anim1->array_num;
  499.       reset[anim1->array_num]=1;                        /* reset anim cell */
  500.       reset[anim2->array_num]=1;
  501.       temp=speedy[anim2->array_num];                  /* swap values */
  502.       speedy[anim2->array_num]=speedy[anim1->array_num];
  503.       speedy[anim1->array_num]=temp;
  504.       temp=speedx[anim2->array_num];
  505.       speedx[anim2->array_num]=speedx[anim1->array_num];
  506.       speedx[anim1->array_num]=temp;
  507.       }
  508. }
  509.  
  510. /***************************************************************************/
  511.  
  512. void cleanup()
  513.  
  514. /* release all resources and memory */
  515.  
  516. {
  517.    free_arrays();
  518.    gs_free_anim(bubble,bubble_cnt);
  519.    gs_remove_display(&bubble_display);
  520.    gs_free_display_list(dlist);
  521.    gs_close_vb_timer();
  522. }
  523.  
  524. /***************************************************************************/
  525.  
  526. void free_arrays()
  527.  
  528. /* release memory used by control arrays */
  529.  
  530. {
  531.    if (x)
  532.       free(x);
  533.    if (y)
  534.       free(y);
  535.    if (speedx)
  536.       free(speedx);
  537.    if (speedy)
  538.       free(speedy);
  539.    if (last)
  540.       free(last);
  541.    if (reset)
  542.       free(reset);
  543.    if (bm3)
  544.       gs_free_bitmap(bm3);
  545. }
  546.